package com.bgc.codegenerate.utils;

import com.bgc.codegenerate.CodeGenerate;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 代码生成器
 */
@Service
@Slf4j
public class CodeGeneratorUtil {

    public static void generate(GenerateConfiguration configuration) throws Exception {
        log.info("开始解析数据库信息");
        Connection connection = null;
        ResultSet rs = null;
        DatabaseMetaData databaseMetaData = null;
        List<TableColumn> columns = new ArrayList<TableColumn>();
        TableColumn column;
        JavaTypeResolver javaTypeResolver = new JavaTypeResolver();
        try {
            // 获取数据库连接
            connection = CodeGeneratorUtil.getConnection();
            databaseMetaData = connection.getMetaData();

            // 获取表结构信息
            rs = databaseMetaData.getColumns(null, null, configuration.getTableName(), "%");
            boolean supportsIsAutoIncrement = false;
            boolean supportsIsGeneratedColumn = false;
            ResultSetMetaData rsmd = rs.getMetaData();
            int colCount = rsmd.getColumnCount();
            for (int i = 1; i <= colCount; i++) {
                if ("IS_AUTOINCREMENT".equals(rsmd.getColumnName(i))) {
                    supportsIsAutoIncrement = true;
                }
                if ("IS_GENERATEDCOLUMN".equals(rsmd.getColumnName(i))) {
                    supportsIsGeneratedColumn = true;
                }
            }
            Set<String> columnSet = new HashSet<>();
            while (rs.next()) {
                if (!columnSet.add(rs.getString("COLUMN_NAME"))) {
                    continue;
                }
                column = new TableColumn();
                column.setJdbcType(rs.getInt("DATA_TYPE"));
                column.setLength(rs.getInt("COLUMN_SIZE"));
                column.setActualColumnName(rs.getString("COLUMN_NAME"));
                column.setNullable(rs.getInt("NULLABLE") == DatabaseMetaData.columnNullable);
                column.setScale(rs.getInt("DECIMAL_DIGITS"));
                column.setRemarks(rs.getString("REMARKS"));
                column.setDefaultValue(rs.getString("COLUMN_DEF"));

                if (supportsIsAutoIncrement) {
                    column.setIsAutoIncrement("YES".equals(rs.getString("IS_AUTOINCREMENT")));
                }
                if (supportsIsGeneratedColumn) {
                    column.setIsGeneratedColumn("YES".equals(rs.getString("IS_GENERATEDCOLUMN")));
                }
                column.setJavaType(javaTypeResolver.get(column));
                column.setJdbcTypeName(javaTypeResolver.calculateJdbcTypeName(column));
                column.setJavaProperty(StringUtils.getCamelCaseString(column.getActualColumnName(), false));
                columns.add(column);
            }
        } catch (SQLException e) {
            log.error("occur an error...", e);
        } finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    log.error("ResultSet 关闭失败");
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    log.error("Connection 关闭失败");
                }
            }
        }
        log.info("数据表信息解析成功!");
        try {
            //输出文件路径
            FileGenerator.writeFile(configuration, columns);// 写文件
        } catch (IOException e) {
            log.error("occur an error...", e);
        } catch (TemplateException e) {
            log.error("occur an error...", e);
        }
    }

    public static Connection getConnection() throws Exception {

        Class.forName(CodeGenerate.DB_DRIVER);
        return DriverManager.getConnection(CodeGenerate.DB_URL, CodeGenerate.DB_USER,
                CodeGenerate.DB_PWD);
    }

}
